package com.kitty.web.client;

import com.kitty.common.utils.SpringUtils;
import com.kitty.cross.core.client.CCSession;
import com.kitty.cross.core.server.BaseCMessageDispatcher;
import com.kitty.cross.core.server.CMessageDispatcher;
import com.kitty.game.fight.service.BroadcastService;
import com.kitty.game.player.model.PlayerProfile;
import com.kitty.game.role.model.Role;
import com.kitty.listener.EventType;
import com.kitty.listener.event.LogoutEvent;
import com.kitty.mina.cache.DataCache;
import com.kitty.mina.cache.SessionUtils;
import com.kitty.mina.codec.SerializerHelper;
import com.kitty.mina.message.Message;
import com.kitty.mina.session.SessionManager;
import com.kitty.mina.session.SessionProperties;
import com.kitty.mina.task.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.nutz.lang.Lang;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import java.net.InetSocketAddress;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Service
@Slf4j
public class ClientSessionManage {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    CMessageDispatcher dispatcher;
    //        private static String HOST = "192.168.43.21";
//    private static int PORT = 8211;
   // private static String HOST = "192.168.1.6";

   // private static int PORT = 8211;
    public void createFightSession(ConcurrentMap<Integer, ConcurrentMap<Integer, IoSession>> sessionMap) {
        int PORT = Integer.parseInt(DataCache.REDIS_DATA.get("port"));
        NioSocketConnector connector = initConn();
        //type ==1 战斗假人。 2 移动升级假人
        String sql = "select sid, roleId, uid, `name`, distName, roleIcon, `level`, polar,enterTime from t_role where aitype = 1";
        List<PlayerProfile> profileList = jdbcTemplate.query(sql,new PlayerRowMapper());
        for (PlayerProfile playerProfile : profileList) {
            int range = getRange(playerProfile.getLevel());
            if(!sessionMap.containsKey(range)){
                sessionMap.put(range,new ConcurrentHashMap<>());
            }
            ConcurrentMap<Integer, IoSession> fightSession = sessionMap.get(range);
            if(!fightSession.containsKey(playerProfile.getRoleId())){
                ConnectFuture future = connector.connect(new InetSocketAddress(PORT));
                future.awaitUninterruptibly();
                IoSession session = future.getSession();
                session.setAttribute(SessionProperties.PLAYER,playerProfile);
                fightSession.putIfAbsent(playerProfile.getRoleId(),session);
            }
        }
    }
    public void createMoveSession(ConcurrentMap<Integer, IoSession> sessionMap) {
        int PORT = Integer.parseInt(DataCache.REDIS_DATA.get("port"));
        NioSocketConnector connector = initConn();
        String sql = "select sid, roleId, uid, `name`, distName, roleIcon, `level`, polar,enterTime from t_role where aitype = 2";
        List<PlayerProfile> profileList = jdbcTemplate.query(sql,new PlayerRowMapper());
        for (PlayerProfile playerProfile : profileList) {
            if(!sessionMap.containsKey(playerProfile.getRoleId())){
                ConnectFuture future = connector.connect(new InetSocketAddress(PORT));
                future.awaitUninterruptibly();
                IoSession session = future.getSession();
                session.setAttribute(SessionProperties.PLAYER,playerProfile);
                sessionMap.putIfAbsent(playerProfile.getRoleId(),session);
            }
        }
    }
    public NioSocketConnector initConn(){
        String HOST = DataCache.REDIS_DATA.get("inetIp");
        int PORT = Integer.parseInt(DataCache.REDIS_DATA.get("port"));
        NioSocketConnector connector = new NioSocketConnector();
        connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(SerializerHelper.getInstance().getCodedFactory()));
        connector.setHandler(new IoHandlerAdapter() {
            @Override
            public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
            }
            @Override
            public void messageReceived(IoSession session, Object data) throws Exception {
                Message message = (Message)data;
                CCSession ccSession = CCSession.valueOf(HOST, PORT,  BaseCMessageDispatcher.getInstance());

                dispatcher.clientDispatch(ccSession, message);
            }
        });
        return connector;
    }

    public int getRange(int level){
        return level/10*10;
    }

    public void removeSession(ConcurrentMap<Integer, IoSession> sessionMap) {
        for (Map.Entry<Integer, IoSession> integerIoSessionEntry : sessionMap.entrySet()) {
            IoSession value = integerIoSessionEntry.getValue();
            PlayerProfile attribute = (PlayerProfile)value.getAttribute(SessionProperties.PLAYER);
            IoSession session = SessionUtils.getSession(attribute.getRoleId());
            if (session != null){
                Role role = SessionUtils.getRoleBySession(session);
                try {
                    ThreadLocalUtil.addLocalTask(role, () -> {
                        onPlayerLogout(role);
                    });
                } catch (Exception e) {
                    log.info("Session关闭错误信息===={}", Lang.getStackTrace(e));
                }
            }
            //integerIoSessionEntry.getValue().closeNow();
        }
    }
    private void onPlayerLogout(Role role) {
        /**产生一个登出事件*/
        SpringUtils.getBean(BroadcastService.class).handleLogoutEvent(new LogoutEvent(EventType.LOGOUT, role));
        /**在线列表删除掉此角色*/
        SpringUtils.getRoleService().removeOnline(role);
        SessionManager.INSTANCE.unRegisterSession(role.getRoleId());

    }
    private class PlayerRowMapper implements RowMapper<PlayerProfile> {

        @Override
        public PlayerProfile mapRow(ResultSet re, int arg1) throws SQLException {
            return new PlayerProfile(re.getString("sid"), re.getInt("roleId"), re.getLong("uid"), re.getString("name"),
                    re.getString("distName"), re.getShort("roleIcon"),
                    re.getShort("level"),
                    re.getShort("polar"), re.getLong("enterTime"));
        }

    }
}
